﻿package com.bizmlib.managers
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import com.bizmlib.ui.display.InteractiveObjectContainer;
	
	
	public class PopupManager extends EventDispatcher
	{
		private static var popupsList:Array;
		
		
		private static var __instance:PopupManager;
		
		
		public static function get instance():PopupManager
		{
			if(!__instance)
			{
				__instance = new PopupManager();
			}
			
			return __instance;
		}
		
		
		public static function showPopUp(view:DisplayObject, parent:DisplayObjectContainer):DisplayObjectContainer
		{
			if(!parent.stage)
			{
				throw new Error("the provided parent is not on a stage");
			}
			
			checkList();
			
			var popupContainer:InteractiveObjectContainer= new InteractiveObjectContainer();
			popupContainer.view = view;
			parent.addChild(popupContainer);
			
			var popupDescriptor:PopupDescriptor = new PopupDescriptor();
			popupDescriptor.popup = popupContainer;
			popupDescriptor.width = popupContainer.width;
			popupDescriptor.height = popupContainer.height;
			popupDescriptor.stageWidth = parent.stage.stageWidth;
			popupDescriptor.stageHeight = parent.stage.stageHeight;
			//trace(parent.stage.stageWidth + "\t" + parent.stage.stageHeight);
			popupDescriptor.centerX = parent.stage.stageWidth/2;
			popupDescriptor.centerY = parent.stage.stageHeight/2;
			popupsList.push(popupDescriptor);
			
			parent.stage.addEventListener(Event.RESIZE, handleStageResize);
			
			locatePopUp(popupDescriptor);
			
			for(var i:Number=0; i<popupsList.length-1; i++)
			{
				disablePopup(popupsList[i] as PopupDescriptor);
			}
			
			instance.dispatchEvent(new PopupManagerEvent(PopupManagerEvent.POPUP_CREATED, popupContainer));
			
			return popupContainer;
		}
		public static function removePopUp(popup:DisplayObjectContainer):void
		{
			checkList();
			
			var popupDescriptor:PopupDescriptor = findPopupDescriptor(popup);
			var popupContainer:InteractiveObjectContainer = popupDescriptor.popup as InteractiveObjectContainer;
			popupContainer.view = null;
			if(popupContainer.parent)
			{
				popupContainer.parent.removeChild(popupContainer);
			}
			popupDescriptor.popup = null;
			
			removePopupDescriptor(popupDescriptor);
			
			if(popupsList.length>0)
			{
				for(var i:Number=0; i<popupsList.length-1; i++)
				{
					disablePopup(popupsList[i] as PopupDescriptor);
				}
				enablePopup(popupsList[popupsList.length-1] as PopupDescriptor);
			}
			
			instance.dispatchEvent(new PopupManagerEvent(PopupManagerEvent.POPUP_REMOVED, popupContainer));
		}
		public static function correctPopUpPosition(popup:DisplayObjectContainer):void
		{
			//trace("PopupManager.correctPopUpPosition(" + arguments + ")");
			
			var popupDescriptor:PopupDescriptor = findPopupDescriptor(popup);
			updatePopupPosition(popupDescriptor);
		}
		public static function centerPopUp(popup:DisplayObjectContainer):void
		{
			var popupDescriptor:PopupDescriptor = findPopupDescriptor(popup);
			popupDescriptor.centerX = popupDescriptor.stageWidth/2;
			popupDescriptor.centerY = popupDescriptor.stageHeight/2;
			locatePopUp(popupDescriptor);
		}
		public static function startPopUpDrag(popup:DisplayObjectContainer):void
		{
			if(!(popup is Sprite))
			{
				return;
			}
			
			var popupSprite:Sprite = popup as Sprite;
			var popupDescriptor:PopupDescriptor = findPopupDescriptor(popup);
			var tlPoint:Point = new Point(0, 0);
			popup.parent.globalToLocal(tlPoint);
			//var bounds:Rectangle = new Rectangle(tlPoint.x - popup.width/2, tlPoint.y - popup.height/2, popup.stage.stageWidth + popup.width, popup.stage.stageHeight + popup.height);
			var bounds:Rectangle = new Rectangle(
				tlPoint.x - popupDescriptor.popupWidth/2,
				tlPoint.y - popupDescriptor.popupHeight/2,
				popup.stage.stageWidth + popupDescriptor.popupWidth,
				popup.stage.stageHeight + popupDescriptor.popupHeight
			);
			popupSprite.startDrag(false, bounds);
		}
		public static function stopPopUpDrag(popup:DisplayObjectContainer):void
		{
			if(!(popup is Sprite))
			{
				return;
			}
			
			var popupSprite:Sprite = popup as Sprite;
			popupSprite.stopDrag();
			
			var popupDescriptor:PopupDescriptor = findPopupDescriptor(popup);
			/**
			popupDescriptor.centerX = popup.x + popup.width/2;
			popupDescriptor.centerY = popup.y + popup.height/2;
			/**/
			popupDescriptor.centerX = popup.x + popupDescriptor.popupWidth/2;
			popupDescriptor.centerY = popup.y + popupDescriptor.popupHeight/2;
			locatePopUp(popupDescriptor);
		}
		
		
		private static function checkList():void
		{
			if(!popupsList)
			{
				popupsList = new Array();
			}
		}
		private static function locatePopUp(popupDescriptor:PopupDescriptor):void
		{
			//trace(popupDescriptor.popup.width + "\t" + popupDescriptor.popup.height);
			var popupPosition:Point = new Point(
				Math.max(0, Math.min(popupDescriptor.centerX - popupDescriptor.popupWidth/2, popupDescriptor.stageWidth - popupDescriptor.popupWidth)),
				Math.max(0, Math.min(popupDescriptor.centerY - popupDescriptor.popupHeight/2, popupDescriptor.stageHeight - popupDescriptor.popupHeight))
			);
			popupPosition.x = Math.round(popupPosition.x);
			popupPosition.y = Math.round(popupPosition.y);
			//trace(popupPosition);
			popupPosition = popupDescriptor.popup.parent.globalToLocal(popupPosition);
			//trace(popupPosition);
			popupDescriptor.popup.x = popupPosition.x;
			popupDescriptor.popup.y = popupPosition.y;
		}
		private static function handleStageResize(event:Event = null):void
		{
			relocatePopups();
		}
		private static function findPopupDescriptor(popup:DisplayObjectContainer):PopupDescriptor
		{
			if(!popupsList)
			{
				return null;
			}
			
			for(var i:Number=0; popupsList.length>i; i++)
			{
				if((popupsList[i] as PopupDescriptor).popup==popup)
				{
					return popupsList[i] as PopupDescriptor;
				}
			}

			return null;
		}
		private static function removePopupDescriptor(popupDescriptor:PopupDescriptor):void
		{
			//trace(this + ".removePopupDescriptor(" + popupDescriptor + ")");
			
			if(!popupsList)
			{
				return;
			}

			for(var i:Number=0; popupsList.length>i; i++)
			{
				if(popupsList[i]==popupDescriptor)
				{
					popupsList.splice(i, 1);
					break;
				}
			}
		}
		private static function updatePopupPosition(popupDescriptor:PopupDescriptor):void
		{
			//trace("PopupManager.updatePopupPosition(" + arguments + ")");
			/**
			var stageDWidth:Number = popupDescriptor.popup.stage.stageWidth - popupDescriptor.stageWidth;
			var stageDHeight:Number = popupDescriptor.popup.stage.stageHeight - popupDescriptor.stageHeight;
			//trace(stageDWidth + "\t" + stageDHeight);
			popupDescriptor.centerX += stageDWidth/2;
			popupDescriptor.centerY += stageDHeight/2;
			/**
			popupDescriptor.centerX = popupDescriptor.centerX * popupDescriptor.popup.stage.stageWidth / popupDescriptor.stageWidth;
			popupDescriptor.centerY = popupDescriptor.centerY * popupDescriptor.popup.stage.stageHeight / popupDescriptor.stageHeight;
			/**
			popupDescriptor.centerX = popupDescriptor.popup.stage.stageWidth/2 - (popupDescriptor.stageWidth/2 - popupDescriptor.centerX);
			popupDescriptor.centerY = popupDescriptor.popup.stage.stageHeight/2 - (popupDescriptor.stageHeight/2 - popupDescriptor.centerY);
			/**/
			locatePopUp(popupDescriptor);
			popupDescriptor.stageWidth = popupDescriptor.popup.stage.stageWidth;
			popupDescriptor.stageHeight = popupDescriptor.popup.stage.stageHeight;
		}
		private static function relocatePopups():void
		{
			for(var i:Number=0; popupsList.length>i; i++)
			{
				updatePopupPosition(popupsList[i] as PopupDescriptor);
			}
		}
		private static function disablePopup(popupDescriptor:PopupDescriptor):void
		{
			var popupContainer:InteractiveObjectContainer = popupDescriptor.popup as InteractiveObjectContainer;
			if(!popupContainer)
			{
				return;
			}
			var previousInteractionEnabledValue:Boolean = popupContainer.interactionEnabled;
			popupContainer.interactionEnabled = false;
			if(previousInteractionEnabledValue)
			{
				instance.dispatchEvent(new PopupManagerEvent(PopupManagerEvent.POPUP_DISABLED, popupContainer.view));
			}
		}
		private static function enablePopup(popupDescriptor:PopupDescriptor):void
		{
			var popupContainer:InteractiveObjectContainer = popupDescriptor.popup as InteractiveObjectContainer;
			if(!popupContainer)
			{
				return;
			}
			popupContainer.interactionEnabled = true;
			instance.dispatchEvent(new PopupManagerEvent(PopupManagerEvent.POPUP_ENABLED, popupContainer.view));
		}

		
		
		override public function toString():String
		{
			return "[PopupManager]";
		}
	}
}

/**/
import flash.display.DisplayObjectContainer;
import com.bizmlib.ui.display.InteractiveObjectContainer;
class PopupDescriptor
{
	public var popup:DisplayObjectContainer;
	public var centerX:Number;
	public var centerY:Number;
	public var width:Number;
	public var height:Number;
	public var stageWidth:Number;
	public var stageHeight:Number;
	
	public function get popupWidth():Number
	{
		if(popup is InteractiveObjectContainer)
		{
			return (popup as InteractiveObjectContainer).view.width;
		}
		
		return popup.width;
	}
	public function get popupHeight():Number
	{
		if(popup is InteractiveObjectContainer)
		{
			return (popup as InteractiveObjectContainer).view.height;
		}
		
		return popup.height;
	}
}
/**
class PopupContainer extends InteractiveObjectContainer
{
	private var __popup:DisplayObject;
	
	
	override public function set width(value:Number):void
	{
	}
	override public function get width():Number
	{
		return popup ? popup.width : 0;
	}
	override public function set height(value:Number):void
	{
	}
	override public function get height():Number
	{
		return popup ? popup.height : 0;
	}
	
	public function set popup(value:DisplayObject):void
	{
		if(popup)
		{
			removeChild(popup);
		}
		
		__popup = value;
		
		if(popup)
		{
			addChild(popup);
		}
	}
	public function get popup():DisplayObject
	{
		return __popup;
	}
}
/**/